package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.dto.PaginationDTO;
import com.example.dto.QuestionByuser;
import com.example.dto.QuestionDto;
import com.example.dto.QuestionQueryDTO;
import com.example.exception.CustomizeErrorCode;
import com.example.exception.CustomizeException;
import com.example.mapper.*;
import com.example.model.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Author by admin, Email xx@xx.com, Date on 2019/8/6.
 * PS: Not easy to write code, please indicate.
 */
@Service
public class Questionservice extends ServiceImpl<QuestionMapper, Question> {
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private NoticeMapper noticeMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired

    private RedisTemplate redisTemplate;
    @Autowired
    private SubscribeMapper subscribeMapper;


    public PaginationDTO Allselect(String search,Integer page, Integer size) {
        if (StringUtils.isNotBlank(search)) {
            String[] tags = StringUtils.split(search, " ");
            search = Arrays
                    .stream(tags)
                    .filter(StringUtils::isNotBlank)
                    .map(t -> t.replace("+", "").replace("*", ""))
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.joining("|"));
        }
        QuestionQueryDTO questionQueryDTO = new QuestionQueryDTO();
        questionQueryDTO.setSearch(search);
        PaginationDTO PaginationDTO = new PaginationDTO();
        Integer totalCount=questionMapper.countbysearch(search);
        if (totalCount==0){
            throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
        }
        Integer totalPage;
        if (totalCount % size == 0) {
            totalPage = totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }

        if (page < 1) {
            page = 1;
        }
        if (page > totalPage) {
            page = totalPage;
        }
        Integer nowrow= size*(page-1);
            PaginationDTO.setPagination(totalPage,page);
            List<Question> allselect  = questionMapper.AllselectBysearch(questionQueryDTO.getSearch(),nowrow,size);
            List<QuestionDto> questionDtoslist = new ArrayList<>();
            allselect.forEach(i->{
                User user = userMapper.selectById(i.getCreator());
                QuestionDto questionDto =null;
                if (user!=null){
                    //获取点赞数
                    Set<String> keysList = redisTemplate.keys("thumbUp_article_"+i.getId()+"*");
                    List<Object> uplist =null;
                    if (keysList!=null){
                        uplist =  redisTemplate.opsForValue().multiGet(keysList);
                        uplist.removeIf(Objects::isNull);
                    }
                    QueryWrapper<UserInfo> Wrapper = new QueryWrapper<>();
                    Wrapper.eq(StringUtils.isNotEmpty(user.getAccountId()),"ACCOUNT_ID",user.getAccountId());
                    UserInfo userInfo = userInfoMapper.selectOne(Wrapper);
                    questionDto = new QuestionDto();
                    BeanUtils.copyProperties(i,questionDto);
                    questionDto.setUser(user);
                    questionDto.setUserInfo(userInfo);
                    questionDto.setThumbup(uplist != null ? uplist.size() : 0);
                    questionDtoslist.add(questionDto);
                }
            });
            PaginationDTO.setData(questionDtoslist);
         return PaginationDTO;
        }


    public PaginationDTO list(User user, Integer page, Integer size) {
        PaginationDTO paginationDTO = new PaginationDTO();
        Integer totalPage;
        Integer totalCount =  questionMapper.count();
        if (totalCount % size == 0) {
            totalPage = totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }

        if (page < 1) {
            page = 1;
        }
        if (page > totalPage) {
            page = totalPage;
        }
        paginationDTO.setPagination(totalPage, page);
        //size*(page-1)
        Integer offset = size * (page - 1);
        List<Question> myquestion  = questionMapper.myquestion(user.getId(), offset,size);
        paginationDTO.setData(myquestion);
        return paginationDTO;
    }


    public QuestionDto getInfoByid(Integer id) {
        Question question = questionMapper.getquetionByid(id);
        QuestionDto questionDto = new QuestionDto();
        if (question==null){
            throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
        }
        //获取点赞状态
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if ("anonymousUser" != authentication.getPrincipal()){
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            Long userId = loginUser.getUser().getId();
            String accountId = loginUser.getUser().getAccountId();
            String key="thumbUp_article_"+id+"_"+accountId+"_"+userId;
            Object flag = redisTemplate.opsForValue().get(key);
            questionDto.setThumbuptytp(flag != null);
        }
        BeanUtils.copyProperties(question,questionDto);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("ID",question.getCreator());
        User user  =   userMapper.selectOne(wrapper);
        QueryWrapper<UserInfo> infoQueryWrapper = new QueryWrapper<>();
        infoQueryWrapper.eq("ACCOUNT_ID",user.getAccountId());
        UserInfo userInfo = userInfoMapper.selectOne(infoQueryWrapper);
        questionDto.setUserInfo(userInfo);
        questionDto.setUser(user);
        return questionDto;

    }

    //添加问题点击次数
    public void incview(Integer id) {
        questionMapper.addview(id);
    }

    public List<QuestionDto> selectRelated(QuestionDto questionDto) {
        if (StringUtils.isBlank(questionDto.getTag())) {
            return new ArrayList<>();
        }
        String[] tags = StringUtils.split(questionDto.getTag(), ",");
        String regexpTag = Arrays
                .stream(tags)
                .filter(StringUtils::isNotBlank)
                .map(t -> t.replace("+", "").replace("*", ""))
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.joining("|"));
        Question question = new Question();
        question.setId(questionDto.getId().longValue());
        question.setTag(regexpTag);
        List<Question> questions = questionMapper.selectRelated(question);
        List<QuestionDto> questionDTOS = questions.stream().map(q -> {
            QuestionDto questionDTO = new QuestionDto();
            BeanUtils.copyProperties(q, questionDTO);
            return questionDTO;
        }).collect(Collectors.toList());
        return questionDTOS;
    }

    @Cacheable(value="thisredis")
    public List<QuestionDto>  selectquestionByView() {
        List<Question> questions = questionMapper.selectquestionByView();
        List<QuestionDto> hotquestionDto = new ArrayList<>();
        for (Question question : questions) {
            QuestionDto questionDto = new QuestionDto();
            //将question中的属性拷贝到questionDta中
            BeanUtils.copyProperties(question,questionDto);
            hotquestionDto.add(questionDto);
        }
        return hotquestionDto;
    }

    public boolean delquestionByuser(User user) {
        QueryWrapper<Question> questionQueryWrapper = new QueryWrapper<>();
        questionQueryWrapper.eq("CREATOR",user.getId());
        return lambdaUpdate().eq(Question::getCreator, user.getId()).remove();
    }

    //根据用户查询所有问题
    public IPage<Question> getQuestionList(QuestionByuser questionByuser) {
        Page<Question> page = new Page<>(questionByuser.getPageNumber(), questionByuser.getPageSize());
        QueryWrapper<Question> wrapper = new QueryWrapper<>();
        wrapper.eq("CREATOR",questionByuser.getId());
        IPage<Question> iPage = questionMapper.selectPage(page, wrapper);
        return iPage;
    }

    //文章点赞
    public void thumpUp(String questionId,Long userId){
        Question question = questionMapper.selectById(questionId);
        Set<String> keysList = redisTemplate.keys("thumbUp_article_"+questionId+"*");
        List<Object> uplist =null;
        if (keysList!=null){
            uplist =  redisTemplate.opsForValue().multiGet(keysList);
            uplist.removeIf(Objects::isNull);
        }
        question.setThumbup(uplist.size());
        questionMapper.updateById(question);
        //点赞通知
        Notice notice = new Notice();
        notice.setReceiverId(question.getCreator().intValue());
        notice.setOperatorId(userId.intValue());
        notice.setAction("thumpUp");
        notice.setTargetType("question");
        notice.setTargetId(Integer.valueOf(questionId));
        notice.setType("sys");
        notice.setState(0);
        notice.setCreatetime(new Date());
        //保存消息
        noticeMapper.insert(notice);
        //创建点赞rabbitmq通知
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
        Queue queue = new Queue("article_thumbup_" + question.getCreator(), true);
        rabbitAdmin.declareQueue(queue);
        rabbitTemplate.convertAndSend("article_thumbup_"+question.getCreator(),"您的文章_"+questionId+"_有点赞消息！");
    }


    public Boolean subscribe(String authorId, String userId) {
        //mysql储存订阅信息
        Subscribe subscribe = new Subscribe();
        subscribe.setAuthorId(Integer.valueOf(authorId));
        subscribe.setUserId(Integer.valueOf(userId));
        subscribeMapper.insert(subscribe);

        //创建Rabbit管理器
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
        //声明exchange
        DirectExchange exchange = new DirectExchange("article_subscribe");
        rabbitAdmin.declareExchange(exchange);
        //创建queue(名称，是否持久化消息)
        Queue queue = new Queue("article_subscribe_" + userId, true);

        //声明exchange和queue的绑定关系，设置路由键为作者id
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(String.valueOf(authorId));

        //设置用户KEY 存放文章作者ID
        String userKey ="article_subscribe_"+userId;
        //设置作者KEY 存放订阅者ID
        String authorKey = "article_author_"+authorId;
        //查询用户集合中是否有该作者的ID
        Boolean flag = redisTemplate.boundSetOps(userKey).isMember(authorId);
        if(flag==true){
            //订阅该作者，就取消订阅
            redisTemplate.boundSetOps(userKey).remove(authorId);
            redisTemplate.boundSetOps(authorKey).remove(userId);
            //从订阅集合中删除作者ID，从订阅者集合中删除用户ID
            //删除绑定的队列
            rabbitAdmin.removeBinding(binding);
            return false;
        }else {
            //没有订阅信息，添加订阅信息。
            redisTemplate.boundSetOps(userKey).add(authorId);
            redisTemplate.boundSetOps(authorKey).add(userId);
            //声明队列和绑定队列
            rabbitAdmin.declareQueue(queue);
            rabbitAdmin.declareBinding(binding);
        }
        return true;
    }




}
